package com.jinmdz.fmis.api.wrapper;

import com.jinmdz.fmis.api.model.system.UserItem;
import com.jinmdz.fmis.common.ext.ArrayListExt;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.common.util.StringUtil;
import com.jinmdz.fmis.common.wrapper.ValidateWrapper;
import com.jinmdz.fmis.core.annotation.AnAuthorize;
import com.jinmdz.fmis.core.base.BaseBean;
import com.jinmdz.fmis.core.base.BaseResult;
import com.jinmdz.fmis.core.model.HandlerInfo;
import com.jinmdz.fmis.core.wrapper.ResultWrapper;
import com.jinmdz.fmis.dao.admin.dao.AdminDao;
import com.jinmdz.fmis.dao.admin.model.admin.AdminMenuButtonListItem;
import com.jinmdz.fmis.dao.admin.model.admin.AdminMenuListItem;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Handler封装处理类
 *
 * @author LiCongLu
 * @date 2020-01-09 14:12
 */
@Component
public class HandlerWrapper {

    @Resource
    private AdminDao adminDao;

    /**
     * 验证访问授权
     *
     * @param userItem    当前账号
     * @param handlerInfo 访问处理信息
     * @param systemCode  系统编码
     * @param menuId      菜单主键
     * @return
     * @author LiCongLu
     * @date 2020-04-02 10:34
     */
    public BaseResult validateAuthorize(UserItem userItem, HandlerInfo handlerInfo, String systemCode, String menuId) {
        // 当处理信息为空时，允许访问
        if (DataUtil.isNull(handlerInfo)) {
            return null;
        }

        // 将授权集合起来
        ArrayListExt<AnAuthorize> authorizeList = new ArrayListExt<>();
        authorizeList.addExt(handlerInfo.getClassAuthorizes());
        authorizeList.addExt(handlerInfo.getMethodAuthorizes());
        // 当不存在注解授权时，允许访问
        if (DataUtil.invalid(authorizeList)) {
            return null;
        }

        // 按照当前账号获取业务系统主键
        Integer systemId = adminDao.getSystemIdBySystemCode(systemCode, userItem.getId());
        // 当前账号未设置系统关联时，禁止访问
        if (DataUtil.invalid(systemId)) {
            return ResultWrapper.failure("当前账号无加载此系统的权限");
        }

        // 获取系统菜单主键值
        Integer systemMenuId = 0;
        if (DataUtil.valid(menuId) && DataUtil.isNumeric(menuId)) {
            try {
                systemMenuId = Integer.parseInt(menuId);
            } catch (Exception e) {
                systemMenuId = 0;
            }
        }

        // 菜单
        ArrayListExt<String> menuList = new ArrayListExt<>();
        ArrayListExt<String> buttonList = new ArrayListExt<>();
        // 按钮菜单
        HashMap<String, ArrayListExt<String>> menuButtonMap = new HashMap<>(16);
        // 解析获取菜单及按钮信息
        for (AnAuthorize anAuthorize : authorizeList) {
            if (DataUtil.valid(anAuthorize.menu())) {
                String menu = anAuthorize.menu();
                buttonList.addExt(anAuthorize.buttons());
                // 累加相同菜单的按钮
                if (menuButtonMap.containsKey(menu)) {
                    menuButtonMap.get(menu).addExt(anAuthorize.buttons());
                    continue;
                }
                // 记录菜单及按钮
                menuList.add(menu);
                menuButtonMap.put(menu, new ArrayListExt<String>().addExt(anAuthorize.buttons()));
            }
        }

        // 注解授权菜单为空时，禁止访问
        if (DataUtil.invalid(menuList)) {
            return ResultWrapper.failure("此接口没有任何可访问授权");
        }

        return validateAuthorizeForMenuButton(userItem, systemId, systemMenuId, menuList, buttonList, menuButtonMap);
    }

    /**
     * @param userItem      当前账号
     * @param systemId      系统主键
     * @param systemMenuId  系统菜单主键
     * @param menuList      菜单集合
     * @param buttonList    按钮集合
     * @param menuButtonMap 菜单按钮集合
     * @return
     * @author LiCongLu
     * @date 2020-04-02 16:06
     */
    private BaseResult validateAuthorizeForMenuButton(UserItem userItem, Integer systemId, Integer systemMenuId
            , ArrayListExt<String> menuList, ArrayListExt<String> buttonList, HashMap<String, ArrayListExt<String>> menuButtonMap) {
        // 按照授权菜单获取菜单主键集合
        ArrayList<AdminMenuListItem> menuListItems = adminDao.listAdminMenuListByMenus(systemId, userItem.getId(), menuList);
        // 当不存在授权菜单时，禁止访问
        if (DataUtil.invalid(menuListItems)) {
            return ResultWrapper.failure("此账号没有此接口的访问权限");
        }

        // 按照授权菜单获取按钮
        ArrayList<AdminMenuButtonListItem> buttonListItems = adminDao.listAdminMenuButtonListByMenus(systemId, userItem.getId(), menuList);
        // 当没有注解按钮授权以及没有设置菜单按钮权限时，允许访问
        if (DataUtil.invalid(buttonList) && DataUtil.invalid(buttonListItems)) {
            return null;
        }

        // 当存在注解授权，但不存在设置菜单按钮权限时，禁止访问
        if (DataUtil.valid(buttonList) && DataUtil.invalid(buttonListItems)) {
            return ResultWrapper.failure("没有此接口的按钮访问权限");
        }

        // 按照系统编码和菜单主键一起验证
        if (DataUtil.valid(systemMenuId)) {
            return validateAuthorizeForSystemMenuId(systemMenuId, menuButtonMap, menuListItems, buttonListItems);
        }

        // 按钮验证标记
        Boolean buttonFlag = false;
        // 当存在注解授权时，并存在设置菜单按钮权限时，逐个菜单验证按钮
        for (Map.Entry<String, ArrayListExt<String>> entry : menuButtonMap.entrySet()) {
            String menuRoute = entry.getKey();
            ArrayListExt<String> buttons = entry.getValue();
            for (AdminMenuButtonListItem buttonItem : buttonListItems) {
                // 只要验证通过一个按钮即可
                if (DataUtil.equals(menuRoute, buttonItem.getMenuRoute())
                        && buttons.contains(buttonItem.getButtonName())) {
                    buttonFlag = true;
                    break;
                }
            }
            if (buttonFlag) {
                break;
            }
        }

        // 判断是否授权菜单按钮
        if (!buttonFlag) {
            return ResultWrapper.failure("没有此接口的按钮访问权限");
        }

        return null;
    }

    /**
     * 当系统菜单主键验证权限
     *
     * @param systemMenuId    菜单主键
     * @param menuButtonMap   菜单按钮映射
     * @param menuListItems   菜单集合
     * @param buttonListItems 菜单按钮集合
     * @return
     * @author LiCongLu
     * @date 2020-04-02 15:56
     */
    private BaseResult validateAuthorizeForSystemMenuId(Integer systemMenuId, HashMap<String, ArrayListExt<String>> menuButtonMap, ArrayList<AdminMenuListItem> menuListItems, ArrayList<AdminMenuButtonListItem> buttonListItems) {
        String menuRoute = "";
        // 菜单验证标记
        boolean menuFlag = false;
        // 查询菜单列表
        for (AdminMenuListItem menuItem : menuListItems) {
            if (DataUtil.equals(menuItem.getId(), systemMenuId)
                    && menuButtonMap.containsKey(menuItem.getMenuRoute())) {
                menuRoute = menuItem.getMenuRoute();
                menuFlag = true;
                break;
            }
        }

        // 判断是否授权菜单
        if (!menuFlag) {
            return ResultWrapper.failure("此菜单没有此接口的访问权限");
        }

        // 获取菜单
        ArrayListExt<String> buttons = menuButtonMap.get(menuRoute);
        // 注解授权按钮时
        if (DataUtil.valid(buttons)) {
            // 验证菜单按钮授权
            Boolean buttonFlag = false;
            for (AdminMenuButtonListItem buttonItem : buttonListItems) {
                if (DataUtil.equals(menuRoute, buttonItem.getMenuRoute())
                        && buttons.contains(buttonItem.getButtonName())) {
                    buttonFlag = true;
                    break;
                }
            }

            // 判断是否授权菜单按钮
            if (!buttonFlag) {
                return ResultWrapper.failure("此菜单没有此接口的按钮访问权限");
            }
        }

        return null;
    }


    /**
     * 验证请求数据
     *
     * @param bean 请求数据
     * @return
     * @author LiCongLu
     * @date 2020-01-09 15:49
     */
    public <T extends BaseBean> BaseResult<String> validateBean(T bean) {
        // 实体不存在
        if (DataUtil.isNull(bean)) {
            return null;
        }

        // 验证数据
        HashMap<String, String> hashMap = ValidateWrapper.validateBean("", bean.getClass(), bean);
        if (hashMap != null && hashMap.size() > 0) {
            String[] values = hashMap.values().toArray(new String[]{});
            return ResultWrapper.failure(StringUtil.joinComma(values));
        }
        return null;
    }

    /**
     * 验证请求集合数据
     *
     * @param beanList 请求数据集合
     * @return
     * @author LiCongLu
     * @date 2020-03-10 09:47
     */
    public <T extends BaseBean> BaseResult validateList(ArrayList<T> beanList) {
        // 集合不存在
        if (DataUtil.invalid(beanList)) {
            return null;
        }

        // 验证数据集合
        HashMap<String, String> hashMap = ValidateWrapper.validateList("", beanList);
        if (hashMap != null && hashMap.size() > 0) {
            String[] values = hashMap.values().toArray(new String[]{});
            return ResultWrapper.failure(StringUtil.joinComma(values));
        }
        return null;
    }
}
